# Copyright (c) 2005,2006,2007 Dynamic Solutions Inc. (support@dynamic-solutions.com)
#
# This file is part of DataZoomer.
#
# DataZoomer is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# DataZoomer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Launch DataZoomer applets

DataZoomer App class

All DataZoomer applications have to do basically one thing.  They have to
return a Response object.  This class assists with that process by recognizing
the 'action' parameter passed in the URL and invoking a method in itself by
the same name (with an _ prepended to prevent tampering).  The other thing
this class does is that if the action method called does not return a response
then this class will decide what to return based on the value of a view variable
either passed in or from the current session.

Note that this class isn't actually a necessary part of DataZoomer.  It is
provided for convenience only.  In DataZoomer any object or function that
returns a response object when called is a valid application.
"""

from dzutil import *

class Controller:
    def __init__(self,app):
        """Controller Initialization"""
        self.app    = app

    def _view_(self):
        return self.app._view_()

    def before_handle(self):
        return 0

    def after_handle(self):
        pass

    def call_handler(self,controller,method):
        """Hanldle an action request"""
        if method != '':
            method = '_%s'%method
            try:
                _mymethod = getattr(controller,method)
            except:
                return controller._unknown(method)
            else:
                params = {}
                for item in zoomer.webvars.__dict__:
                    if not item in ['sid','app','con','action'] and item[0]!='_':
                        params[item] = zoomer.webvars.__dict__[item]
                return _mymethod(**params)

    def _unknown(self,method):
        print 'Unknown method %s.%s' % (self.__class__.__name__,method)

class App(Controller):
    def __init__(self,myname=None):
        def get_app_name():
            import os.path
            (d,app_name) = os.path.split(os.path.abspath('.'))
            return app_name
        Controller.__init__(self,self)

        self.name = myname or get_app_name()
        product = zoomer.db('select * from dz_products where name=%s', self.name)
        if len(product)>0:
           product = product[0]
           self.subtitle    = product.SUBTITLE
           self.iconname    = product.ICONNAME
           self.version     = product.VERSION
           self.userid      = product.USERID
           self.system_app  = product.SYSTEM
           self.position    = product.POSITION
           self.visible     = product.VISIBLE
           self.title       = product.TITLE
           self.status      = product.STATUS
        else:
           self.subtitle    = ''
           self.iconname    = 'blank_doc'
           self.version     = '0.1'
           self.userid      = ''
           self.system_app  = 0
           self.position    = 1
           self.visible     = 1
           self.title       = self.name.capitalize()
           self.status      = 'U'
        self.content = 'Hello World!'
        self.url = url_for(app=self.name)
        self.actions = []
        self.controllers = []
        self.css = 0

        self.set_controller_name(zoomer.webvars.con or 'index')

    def get_view_list(self):
        return [name[6:] for name in dir(self) if name.startswith('_view_') and not name in ['_view_','_view_unknown']]

    def make_view_url(self,view_name):
        return '?sid=%s&app=%s&view=%s' % (zoomer.sid,self.name,view_name)

    def run(self):
        if not self.before_dispatch():
            t = self.dispatch()
            self.after_dispatch()
            return t

    def dispatch(self):
        """Decide which controller is going to handle the request and if necessary render a view"""

        action_view = 0
        if self.controller_name:
            member_name = '_%s' % self.controller_name
            try:
                controller = getattr(self,member_name)
#                if not isinstance(controller):
#                    controller = controller(self)
#                    if not isinstance(controller):
#                        raise 'Unknown controller %s',member_name
#                print repr(controller).replace('<','[')
            except:
#                raise
                try:
                    method = getattr(self.__class__,member_name)
                    controller = method(self)
                except:
#                    print 'Unknown controller %s' % member_name
                    controller = self
        else:
            controller = self

        if not controller.before_handle():
            action_view = self.call_handler(controller,zoomer.webvars.action)
            controller.after_handle()

        if action_view!=None:
            current_view = action_view
        else:
            current_view = controller._view_()

        try:
            result = current_view.render()
        except:
            print 'Error rendering view "%s"' % current_view
            raise
        return result

    def before_dispatch(self):
        pass

    def after_dispatch(self):
        pass

    def _view_(self):
        return self.page(render('views/index.txt',obj=self))

    def set_controller_name(self,new_name):
        self.controller_name = new_name


if __name__ == '__main__':
    import unittest

    class AppTest(unittest.TestCase):

        #----------------------
        def test_App_init(self):
            app = App('myapp')

            self.assertEquals(app.name,'myapp')
            self.assertEquals(app.title,'Myapp')
            self.assertEquals(app.content,'Hello World!')
            self.assertEquals(app.version,'0.1')
            self.assertEquals(app.hint,'')
            self.assertEquals(app.iconname,'blank_doc')
            self.assertEquals(app.contenttype,'html')
            self.assertEquals(app.system_app,0)
            self.assertEquals(app.visible,1)

    unittest.main()
